/*
 * BodyNode.h
 *
 * Part of libai/NNlib
 *
 * (c) 2008 Benjamin Russell, Matthew Russell
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#ifndef BODYNODE_H_
#define BODYNODE_H_

#include "HeadNode.h"

template <typename T>
class BodyNode : public HeadNode<T>
{
public:
    BodyNode();
    virtual ~BodyNode();

    void Add_Input(T in_Input, T in_Weight);
    void Remove_Input(unsigned int N);

    void Add_Source(HeadNode<T>* in_Node, T in_Weight);
    void Add_Source(T in_Source_Val, T in_Weight);

    void Set_Source(unsigned int N, HeadNode<T>* in_Node);
    void Remove_Source(unsigned int N);
    void Update_Inputs();

private:
    std::vector<HeadNode<T>*> Sources;
};

template <typename T>
BodyNode<T>::BodyNode()
    : HeadNode<T>()
{
}

template <typename T>
BodyNode<T>::~BodyNode()
{
    Sources.clear();
}

template <class T>
void BodyNode<T>::Add_Input(T in_Input, T in_Weight)
{
    HeadNode<T>::Inputs.push_back(in_Input);
    HeadNode<T>::Weights.push_back(in_Weight);
    Sources.push_back(NULL);
}

template <class T>
void BodyNode<T>::Remove_Input(unsigned int N)
{
    HeadNode<T>::Inputs.erase(HeadNode<T>::Inputs.begin() + N);
    HeadNode<T>::Weights.erase(HeadNode<T>::Weights.begin() + N);
    Sources.erase(Sources.begin() + N);
}


template <typename T>
void BodyNode<T>::Add_Source(T in_Source_Val, T in_Weight)
{
    Sources.push_back(NULL);
    HeadNode<T>::Weights.push_back(in_Weight);
    HeadNode<T>::Inputs.push_back(in_Source_Val);
}

template <typename T>
void BodyNode<T>::Add_Source(HeadNode<T>* in_Node, T in_Weight)
{
    Sources.push_back(in_Node);
    HeadNode<T>::Weights.push_back(in_Weight);
    HeadNode<T>::Inputs.push_back(in_Node->Get_Output());
}

template <typename T>
void BodyNode<T>::Set_Source(unsigned int N, HeadNode<T>* in_Node)
{
    Sources[N] = in_Node;
}

template <typename T>
void BodyNode<T>::Remove_Source(unsigned int N)
{
    Sources.erase(N);
    HeadNode<T>::Weights.erase(N);
    HeadNode<T>::Inputs.erase(N);
}

template <typename T>
void BodyNode<T>::Update_Inputs()
{
    unsigned int Inputs_Size = HeadNode<T>::Inputs.size();

    for (unsigned int i = 0; i < Inputs_Size; i++)
    {
        if (Sources[i] != NULL)
        {
            HeadNode<T>::Inputs[i] = Sources[i]->Get_Output();
        }
    }
}

#endif /* BODYNODE_H_ */

